package util

import (
	"crypto/aes"
	cipher2 "crypto/cipher"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
)

func errBuilder(message string, datas ...interface{}) error {
	ree := errors.New(fmt.Sprintf(message, datas))
	return ree
}
func RSAEncrypt(message string, pubPath string) (string, error) {
	file, file_err := os.Open(pubPath)
	if file_err != nil {
		e := errBuilder("打开公钥失败：%s", file_err.Error())
		log.Fatalln(e.Error())
		return "", e
	}
	pemData, pem_err := io.ReadAll(file)
	if pem_err != nil {
		e := errBuilder("打开公钥失败：%s", file_err.Error())
		log.Fatalln(e.Error())
		return "", e
	}
	if pemData != nil && len(pemData) != 0 {
		pem_block, _ := pem.Decode(pemData)
		if pem_block == nil {
			e := errBuilder("无法正确解析！")
			log.Fatalln(e.Error())
			return "", e
		} else {
			publicKey, err := x509.ParsePKIXPublicKey(pem_block.Bytes)
			if err != nil {
				e := errBuilder("该公钥不正确，无法正确解析！原因：%s", err.Error())
				log.Fatalln(e.Error())
				return "", e
			} else {
				rsa_public_key := publicKey.(*rsa.PublicKey)
				pass, _ := rsa.EncryptOAEP(sha256.New(), rand.Reader, rsa_public_key, []byte(message), nil)
				return string(pass), nil
			}
		}
	} else {
		e := errBuilder("公钥数据文件为空，请确保该文件是公钥！")
		log.Fatalln(e.Error())
		return "", e
	}
}
func RSADecrypt(message string, priPath string) (string, error) {
	file, file_err := os.Open(priPath)
	if file_err != nil {
		e := errBuilder("打开私钥失败：%s", file_err.Error())
		log.Fatalln(e.Error())
		return "", e
	}
	pemData, pem_err := io.ReadAll(file)
	if pem_err != nil {
		e := errBuilder("打开私钥失败：%s", file_err.Error())
		log.Fatalln(e.Error())
		return "", e
	}
	if pemData != nil && len(pemData) != 0 {
		pem_block, _ := pem.Decode(pemData)
		if pem_block == nil {
			e := errBuilder("无法正确解析！")
			log.Fatalln(e.Error())
			return "", e
		} else {
			privateKey, s1err := x509.ParsePKCS1PrivateKey(pem_block.Bytes)
			if s1err != nil {
				private8Key, s8err := x509.ParsePKCS8PrivateKey(pem_block.Bytes)
				if s8err != nil {
					e := errBuilder("该私钥不是标准格式，请使用PKCS1或PKCS8格式的私钥。")
					log.Fatalln(e.Error())
					return "", e
				} else {
					privateKey = private8Key.(*rsa.PrivateKey)
					pass, _ := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, []byte(message), nil)
					return string(pass), nil
				}
			} else {
				rsa_public_key := privateKey
				pass, _ := rsa.DecryptOAEP(sha256.New(), rand.Reader, rsa_public_key, []byte(message), nil)
				return string(pass), nil
			}
		}
	} else {
		e := errBuilder("私钥数据文件为空，请确保该文件是私钥！")
		log.Fatalln(e.Error())
		return "", e
	}
}
func AESEncrypt(message string, key string) (string, error) {
	cipher, err := aes.NewCipher([]byte(key))
	if err != nil {
		e := errBuilder("无法创建验证%s", err.Error())
		log.Fatalln(e.Error())
		return "", e
	}
	gcm, err2 := cipher2.NewGCM(cipher)
	if err2 != nil {
		e := errBuilder("密钥长度错误%s", err2.Error())
		log.Fatalln(e.Error())
		return "", e
	}
	nonce := make([]byte, gcm.NonceSize())
	rand.Read(nonce)
	return string(gcm.Seal(nonce, nonce, []byte(message), nil)), err
}
func AESDecrypt(message string, key string) (string, error) {
	cipher, _ := aes.NewCipher([]byte(key))
	gcm, _ := cipher2.NewGCM(cipher)
	nonceSize := gcm.NonceSize()
	if len(message) < nonceSize {
		return "", errBuilder("解密失败，数据长度不正确")
	}
	nonce, message := message[:nonceSize], message[nonceSize:]
	plain, err := gcm.Open(nil, []byte(nonce), []byte(message), nil)
	if err != nil {
		e := errBuilder("解密失败")
		log.Fatalln(e.Error())
		return "", e
	} else {
		return string(plain), nil
	}
}
